package com.yuncheng.spcyApi.scheduleJob;

import com.yuncheng.spcyApi.entity.SpcyScheduleSetting;
import com.yuncheng.spcyApi.service.ISpcyScheduleSettingService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.Objects;


public class SchedulingRunnable implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(SchedulingRunnable.class);

    private CronTaskRegistrar cronTaskRegistrar;

    private ISpcyScheduleSettingService spcyScheduleSettingService;

    private String jobId = "0"; // 执行任务id

    private String beanName;

    private String methodName;

    private String params;

    public SchedulingRunnable(String beanName, String methodName) {
        this(beanName, methodName, null);
    }

    public SchedulingRunnable(String beanName, String methodName, String params) {
        this.beanName = beanName;
        this.methodName = methodName;
        this.params = params;
    }

    public SchedulingRunnable(String jobId,String beanName, String methodName, String params) {
        this.jobId = jobId;
        this.beanName = beanName;
        this.methodName = methodName;
        this.params = params;
    }

    public SchedulingRunnable(CronTaskRegistrar cronTaskRegistrar,ISpcyScheduleSettingService spcyScheduleSettingService,String jobId,String beanName, String methodName, String params) {
        this.cronTaskRegistrar = cronTaskRegistrar;
        this.spcyScheduleSettingService = spcyScheduleSettingService;
        this.jobId = jobId;
        this.beanName = beanName;
        this.methodName = methodName;
        this.params = params;
    }

    @Override
    public void run() {

        logger.info("定时任务id: {}",jobId);
        logger.info("定时任务开始执行 - bean：{}，方法：{}，参数：{}", beanName, methodName, params);
        long startTime = System.currentTimeMillis();

        try {
            Object target = SpringConUtils.getBean(beanName);

            boolean isExistParam = false;
            for (Method m : target.getClass().getDeclaredMethods()){
                if (m.getName().equals(methodName)){
                    Class<?>[] parameterTypes = m.getParameterTypes();
                    if (parameterTypes.length > 0){
                        isExistParam = true;
                    }
                    break;
                }
            }

            Method method = null;
            if (isExistParam){
                method = target.getClass().getDeclaredMethod(methodName, String.class);
            }else {
                method = target.getClass().getDeclaredMethod(methodName);
            }
            /*if (!StringUtils.isEmpty(params)) {
                method = target.getClass().getDeclaredMethod(methodName, String.class);
            } else {
                method = target.getClass().getDeclaredMethod(methodName);
            }*/

            ReflectionUtils.makeAccessible(method);
            /*if (!StringUtils.isEmpty(params)) {
                method.invoke(target, params);
            } else {
                method.invoke(target);
            }*/
            if (isExistParam){
                method.invoke(target, params);
            }else {
                method.invoke(target);
            }
        } catch (Exception ex) {
            logger.error(String.format("定时任务执行异常 - bean：%s，方法：%s，参数：%s ", beanName, methodName, params), ex);
        }

        long times = System.currentTimeMillis() - startTime;
        logger.info("定时任务执行结束 - bean：{}，方法：{}，参数：{}，耗时：{} 毫秒", beanName, methodName, params, times);

        if (StringUtils.isNotBlank(jobId) && !jobId.equals("0")) {
            SpcyScheduleSetting sysJob = spcyScheduleSettingService.getById(jobId);
            if (sysJob == null){
                logger.error("定时任务为空");
                return;
            }
            sysJob.setJobStatus(0);
            spcyScheduleSettingService.updateById(sysJob); // 暂停定时任务
            logger.info("暂停定时任务: bean：{}，方法：{}，参数：{}",beanName, methodName, params);
            // 删除成功时要清除定时任务器中的对应任务
            SchedulingRunnable task = new SchedulingRunnable(beanName, methodName, params);
            cronTaskRegistrar.removeCronTask(task);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SchedulingRunnable that = (SchedulingRunnable) o;
        if (params == null) {
            return beanName.equals(that.beanName) &&
                    methodName.equals(that.methodName) &&
                    that.params == null;
        }

        return beanName.equals(that.beanName) &&
                methodName.equals(that.methodName) &&
                params.equals(that.params);
    }

    @Override
    public int hashCode() {
        if (params == null) {
            return Objects.hash(beanName, methodName);
        }

        return Objects.hash(beanName, methodName, params);
    }
}
